package com.itheima.blog.article.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.api.client.WebUserClient;

import com.itheima.api.entity.WebUser;
import com.itheima.blog.article.dto.AnswerDto;
import com.itheima.blog.article.dto.CommentDto;
import com.itheima.blog.article.entity.TBlog;
import com.itheima.blog.article.entity.TComment;
import com.itheima.blog.article.mapper.TBlogMapper;
import com.itheima.blog.article.mapper.TCommentMapper;
import com.itheima.blog.article.query.CommentQuery;
import com.itheima.blog.article.query.PageQueryDTO;

import com.itheima.blog.article.service.ITBlogService;
import com.itheima.blog.article.service.ITCommentService;
import com.itheima.blog.article.vo.CommentVo;
import com.itheima.blog.article.vo.ReplyVO;

import com.itheima.blog.util.UserThreadLocalUtils;
import com.itheima.common.domain.PageReqDto;
import com.itheima.common.domain.PageResDto;
import com.itheima.common.exception.BadRequestException;
import com.itheima.common.exception.BizIllegalException;
import com.itheima.common.utills.BeanUtils;
import com.itheima.common.utills.CollUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.itheima.common.constants.Constant.BLOG_ADD_KEY;
import static com.itheima.common.constants.Constant.BLOG_CLICK_KEY;

/**
 * <p>
 * 评论表 服务实现类
 * </p>
 *
 * @author lin
 * @since 2023-07-12
 */
@Service
@RequiredArgsConstructor
public class TCommentServiceImpl extends ServiceImpl<TCommentMapper, TComment> implements ITCommentService {
    private final WebUserClient webUserClient;
    private final TBlogMapper blogMapper;
    private final StringRedisTemplate redisTemplate;
    private final ITBlogService blogService;
    /**
     * 评论的分页展示查询
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public PageResDto<CommentVo> findPageList(CommentDto dto) {
        Page<TComment> page=new Page<>();
        page.setCurrent(dto.getPage());
        page.setSize(dto.getSize());
        String nickName = dto.getNickName();
        List<Integer> userIds=new ArrayList<>();
        if (nickName!=null) {
            userIds = webUserClient.findUserIdListByNickName(nickName);
        }
        //分页查询
        Page<TComment> pageData = lambdaQuery()
                .in(CollUtils.isNotEmpty(userIds), TComment::getUserId, userIds)
                .like(StringUtils.isNotBlank(dto.getContent()), TComment::getContent, dto.getContent())
                .orderByDesc(TComment::getCreateTime)
                .page(page);
        List<TComment> records = pageData.getRecords();
        if (CollUtils.isEmpty(records)){
            throw new BadRequestException("无数据");
        }
        //转换vo
        List<CommentVo> voList = BeanUtils.copyList(records, CommentVo.class);
        //查询评论人用户信息
//        List<Integer> userIds = records.stream().map(TComment::getUserId).collect(Collectors.toList());
        List<Integer> currentUserIds = records.stream().filter(c ->
                c.getUserId() != null).map(TComment::getUserId).collect(Collectors.toList());
        Map<Integer, WebUser> userMap=null;
        if (CollUtils.isNotEmpty(currentUserIds)){
            List<WebUser> userList = webUserClient.findUserList(currentUserIds);
            userMap= userList.stream().collect(Collectors.toMap(WebUser::getId, u -> u));
        }
        //查询被评论人用户信息
//        List<Integer> targetUserIds = records.stream().map(TComment::getTargetUserId).collect(Collectors.toList());
        List<Integer> targetUserIds = records.stream().filter(c ->
                c.getTargetUserId() != null).map(TComment::getTargetUserId).collect(Collectors.toList());
        Map<Integer, WebUser> tatgetUserMap=null;
        if (CollUtils.isNotEmpty(targetUserIds)){
            List<WebUser> targetUserList = webUserClient.findUserList(targetUserIds);
            tatgetUserMap = targetUserList.stream().collect(Collectors.toMap(WebUser::getId, u -> u));
        }

        //封装vo
        for (CommentVo vo : voList) {
            //评论人昵称、头像
            if (userMap!=null) {
                WebUser webUser = userMap.get(vo.getUserId());
                vo.setImage(webUser.getImage());
                vo.setNickname(webUser.getNickname());
            }
            //被评论人昵称
            if (tatgetUserMap!=null) {
                WebUser targetUser = tatgetUserMap.get(vo.getTargetUserId());
                vo.setTargetNickname(targetUser.getNickname());
            }
        }
        return new PageResDto(dto,pageData.getTotal(),voList);
    }

    /**
     * 删除级联评论
     * @param ids
     */
    @Override
    public void delComment(List<Long> ids) {
        if (ids==null){
            throw new BadRequestException("检查参数");
        }
        //根据id查询一级评论id
        List<TComment> comments = lambdaQuery()
                .in(TComment::getId, ids)
                .list();
        if(CollUtils.isEmpty(comments)){
            throw new BadRequestException("无法删除，请检查参数");
        }
        for (TComment comment : comments) {
            Long commentId = comment.getCommentId();
            for (Long id : ids) {
                //如果是一级评论
                if (commentId!=null){
                    //删除当前评论(真删)
                    this.removeById(id);
                    //删除该评论及评论下的所有评论
                    if (comment.getTargetCommentId()!=null) {
                        LambdaQueryChainWrapper<TComment> qw = lambdaQuery().eq(TComment::getTargetCommentId, commentId);
                        this.remove(qw);
                    }
                }else {
                    //如果是二级评论，删除本身
                    this.removeById(id);
                }
            }
        }
    }
    /**
     * 分页展示评论
     * @param dto
     * @return
     */
    @Override
    public PageResDto<ReplyVO> findPageComment(PageQueryDTO dto) {
         /*
        展示以及评论和二级评论
        回复评论只能回复一级
        点击回复打开输入框
        二级评论不再显示回复按钮
        可以删除自己评论，博主可以删除自己文章下的评论
         */
        Page<TComment> page=new Page<>();
        page.setCurrent(dto.getPage());
        page.setSize(dto.getSize());
        Long blogId = dto.getBlogId();
        Long commentId = dto.getCommentId();
        if (blogId ==null){
            return null;
        }
//        Integer webUserId = UserThreadLocalUtils.getWebUserId();
        Page<TComment> pageData=new Page<>();
        if (commentId!=null) {
            //一级评论
            pageData = lambdaQuery()
                    .eq(TComment::getBlogId, blogId)
//                    .eq(TComment::getTargetCommentId,0L)
                    .eq(commentId!=null,TComment::getCommentId,commentId)
//                    .eq(TComment::getUserId,webUserId)
                    .orderByDesc(TComment::getCreateTime)
                    .page(page);
        }
        else {
            //二级评论
            pageData = lambdaQuery()
                    .eq(blogId!=null,TComment::getBlogId, blogId)
//                    .eq(TComment::getCommentId, 0L)
//                    .eq(TComment::getUserId,webUserId)
                    .eq(TComment::getTargetCommentId,dto.getTargetCommentId())
                    .orderByDesc(TComment::getCreateTime)
                    .page(page);
        }
        List<TComment> records = pageData.getRecords();
        if (CollUtils.isEmpty(records)){
            return null;
        }
        //收集用户一级评论用户信息
        Set<Integer> userIds = records.stream().map(TComment::getUserId).collect(Collectors.toSet());
        List<WebUser> userList = webUserClient.findUserList(userIds);
        if (CollUtils.isEmpty(userIds)){
            throw new BadRequestException("没有查询到该用户信息");
        }
        Map<Integer, WebUser> cuurentUserMap = userList.stream().collect(Collectors.toMap(WebUser::getId, u -> u));
        //收集用户二级评论用户信息
        Set<Integer> targetUserIds = records.stream().map(TComment::getTargetUserId).collect(Collectors.toSet());
        List<WebUser> targetUserList = webUserClient.findUserList(targetUserIds);
        if (CollUtils.isEmpty(userIds)){
            throw new BadRequestException("没有查询到该用户信息");
        }
        Map<Integer, WebUser> targetUserMap = targetUserList.stream().collect(Collectors.toMap(WebUser::getId, u -> u));
        //封装
        List<ReplyVO> voList = records.stream().map(tc -> {
            ReplyVO replyVO = BeanUtils.copyBean(tc, ReplyVO.class);
            WebUser webUser = cuurentUserMap.get(tc.getUserId());
            replyVO.setUserId(webUser.getId());
            replyVO.setNickName(webUser.getNickname());
            replyVO.setImage(webUser.getImage());
            WebUser targetWebUser = targetUserMap.get(tc.getTargetUserId());
            replyVO.setTargetUserId(targetWebUser.getId());
            replyVO.setTargetNickName(targetWebUser.getNickname());
            replyVO.setTargetImage(targetWebUser.getImage());
            return replyVO;
        }).collect(Collectors.toList());
        return new PageResDto<>(dto,pageData.getTotal(),voList);
    }

    /**
     * 新增回复/评论
     * @param dto
     */
    @Override
    public void saveAnswer(AnswerDto dto) {
        Integer webUserId = UserThreadLocalUtils.getWebUserId();
//        TComment comment = BeanUtils.copyBean(dto, TComment.class);
        TComment comment = new TComment();
        comment.setContent(dto.getContent());
        comment.setUserId(webUserId);
        comment.setCreateTime(LocalDateTime.now());
        Long blogId = dto.getBlogId();
        if (blogId!=null){
            comment.setBlogId(blogId);
            TBlog blog= blogService.getById(blogId);
            comment.setTargetUserId(blog.getUserId());
        }
        save(comment);
        redisTemplate.opsForHash().increment(BLOG_ADD_KEY,comment.getBlogId().toString(),1);
        if (dto.getCommentId()==null) {
            comment.setCommentId(comment.getId());
            updateById(comment);
        }else {
            comment.setTargetCommentId(dto.getCommentId());
            updateById(comment);
        }
    }

    @Override
    public void delMyComment(CommentQuery query) {
        Integer webUserId = UserThreadLocalUtils.getWebUserId();
        Long commentId = query.getCommentId();
        Long blogId = query.getBlogId();
        Integer userId = query.getUserId();
        Long id = query.getId();
        List<Long> ids = CollUtils.toList(id);
        //查询userId
        Integer blogUserId=blogMapper.selectUserId(blogId);
        if (blogUserId.equals(userId)){
            //博主
            delComment(ids);
        }else if (!blogUserId.equals(userId)){
            TComment comment = lambdaQuery()
                    .eq(TComment::getId, id)
                    .eq(TComment::getBlogId, blogId)
                    .one();
            if (comment.getUserId().equals(userId)) {
                //可以删除自己的评论
                delComment(ids);
            }
        }else {
            throw new BadRequestException("不能删除该评论");
        }
    }

    @Override
    public PageResDto<TComment> findCommentList(PageReqDto pageReqDto) {
        //获取分页条件
        Integer page = pageReqDto.getPage();
        Integer size = pageReqDto.getSize();
        int i = (page - 1) * size;
        Integer webUserId = UserThreadLocalUtils.getWebUserId();
        //获取分页数据
        Page<TComment> tWebNavbarPage = lambdaQuery()
                .eq(TComment::getUserId,webUserId)
                .orderByDesc(TComment::getCreateTime)
                .page(new Page<>(i, size));
        List<TComment> records = tWebNavbarPage.getRecords();
        return new PageResDto<>(pageReqDto,tWebNavbarPage.getTotal(), records);
    }

    @Override
    public PageResDto<TComment> findReplyList(PageReqDto pageReqDto) {
        //获取分页条件
        Integer page = pageReqDto.getPage();
        Integer size = pageReqDto.getSize();
        int i = (page - 1) * size;
        Integer webUserId = UserThreadLocalUtils.getWebUserId();
        //获取分页数据
        Page<TComment> tWebNavbarPage = lambdaQuery()
                .eq(TComment::getTargetUserId,webUserId)
                .orderByDesc(TComment::getCreateTime)
                .page(new Page<>(i, size));
        List<TComment> records = tWebNavbarPage.getRecords();
        return new PageResDto<>(pageReqDto,tWebNavbarPage.getTotal(), records);
    }
}
